#ifndef CMAINVIEW_HPP
#define CMAINVIEW_HPP

#include <math.h>
#include <time.h>
#include <shlobj.h>
#include <shtypes.h>
#include <windows.h>
#include <strsafe.h>
#include <commctrl.h>

class CMainView
{
public:
    ~CMainView() {}
    CMainView(LPCTSTR lpszClassName, HINSTANCE hInstance)
    {
        m_nMenuBarHeight = 0;
        m_nToolBarHeight = 0;
        m_hWnd = NULL;
        m_hParent = NULL;
        m_hFont = NULL;
        m_hLeftWnd = NULL;
        m_hRightWnd = NULL;
        m_nSplitterWidth = 250;
        m_wcex = {0};
        m_rcMenuBar = {0};
        m_rcToolBar = {0};
        Register(lpszClassName, hInstance);
    }
    CMainView(const CMainView &) = delete;
    CMainView &operator=(const CMainView &) = delete;
    HWND GetHWND() const
    {
        return m_hWnd;
    }
    void SetToolBarRect(RECT rcToolBar)
    {
        m_rcToolBar = rcToolBar;
    }
    void SetMenuBarRect(RECT rcMenuBar)
    {
        m_rcMenuBar = rcMenuBar;
    }
    HWND GetLefthWnd()
    {
        return m_hLeftWnd;
    }
    HWND GetRighthWnd()
    {
        return m_hRightWnd;
    }
    HFONT GetFont(TCHAR *lpFont, UINT uSize = 20)
    {
        if (m_hFont)
        {
            return m_hFont;
        }
        else
        {
            LOGFONT logfont;
            ZeroMemory(&logfont, sizeof(LOGFONT));
            logfont.lfHeight = uSize;
            if (lpFont)
            {
                StringCchCopy(logfont.lfFaceName, 255, lpFont);
            }
            else
            {
                StringCchCopy(logfont.lfFaceName, 255, TEXT("Microsoft YaHei"));
            }
            m_hFont = CreateFontIndirect(&logfont);
            return m_hFont;
        }
    }
    LRESULT Register(LPCTSTR lpszClassName, HINSTANCE hInstance)
    {
        m_wcex = {0};
        m_wcex.cbSize = sizeof(WNDCLASSEX);
        m_wcex.cbClsExtra = 0;                                                                       // 类的额外内存
        m_wcex.cbWndExtra = 0;                                                                       // 窗口额外内存
        m_wcex.hbrBackground = GetSysColorBrush(/*COLOR_3DFACE*/ COLOR_3DSHADOW /*COLOR_3DSHADOW*/); // 背景
        m_wcex.hCursor = LoadCursor(NULL, IDC_ARROW);                                                // 光标 第一个为NULL代表使用系统提供的光标
        m_wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);                                              // 图标 第一个为NULL代表使用系统提供的图标
        m_wcex.hInstance = hInstance;                                                                // 应用程序实例句柄
        m_wcex.lpfnWndProc = CMainView::WndProc;                                                     // 回调函数
        m_wcex.lpszClassName = lpszClassName;                                                        // 窗口类名称
        m_wcex.lpszMenuName = NULL;                                                                  // 菜单名称
        m_wcex.style = CS_HREDRAW | CS_VREDRAW;                                                      // 显示风格
        m_hInstance = hInstance;
        m_lpszMainClassName = lpszClassName;
        if (!RegisterClassEx(&m_wcex))
        {
            MessageBox(NULL, TEXT("Failed to register child window class"), TEXT("Error"), MB_OK | MB_ICONERROR);
            return -1;
        }

        // Intilaizing the class for the lefthand side window
        m_wcex.lpfnWndProc = CMainView::LeftWndProc;
        m_wcex.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
        m_wcex.lpszClassName = TEXT("LeftWindow");
        m_lpszLeftClassName = m_wcex.lpszClassName;
        if (!RegisterClassEx(&m_wcex))
        {
            MessageBox(NULL, TEXT("Failed to register child window class"), TEXT("Error"), MB_OK | MB_ICONERROR);
            return -1;
        }

        // Intilaizing the class for the righthand side window
        m_wcex.lpfnWndProc = CMainView::RightWndProc;
        m_wcex.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
        m_wcex.lpszClassName = TEXT("RightWindow");
        m_lpszRightClassName = m_wcex.lpszClassName;
        if (!RegisterClassEx(&m_wcex))
        {
            MessageBox(NULL, TEXT("Failed to register child window class"), TEXT("Error"), MB_OK | MB_ICONERROR);
            return -1;
        }
        return 0;
    }
    LRESULT Create(HWND hParent, LPRECT lpRect, LPCTSTR szWindowName)
    {
        RECT rect;
        if (!lpRect)
        {
            GetClientRect(hParent, &rect);
            lpRect = &rect;
        }
        m_nMenuBarHeight = m_rcMenuBar.bottom - m_rcMenuBar.top;
        m_nToolBarHeight = m_rcToolBar.bottom - m_rcToolBar.top;
        lpRect->top += m_nToolBarHeight;
        m_hWnd = CreateWindow(m_lpszMainClassName, szWindowName, WS_CHILD | WS_VISIBLE,
                              lpRect->left, lpRect->top, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top,
                              hParent, NULL, m_hInstance, this);
        m_hParent = hParent;
        CreateLeftRightWnd(m_hWnd);
        SetWindowLongPtr(m_hWnd, GWLP_USERDATA, (LONG_PTR)this);
        return 0;
    }
    LRESULT CreateLeftRightWnd(HWND hWnd)
    {
        // create the left window
        RECT rect;
        GetClientRect(hWnd, &rect);
        m_hLeftWnd = CreateWindowEx(WS_EX_CLIENTEDGE, m_lpszLeftClassName, TEXT(""),
                                    WS_CHILD | WS_VISIBLE | SS_SUNKEN,
                                    rect.left,
                                    rect.top,
                                    rect.left + m_nSplitterWidth,
                                    rect.bottom,
                                    hWnd, NULL, m_hInstance, NULL);

        // create the right window
        m_hRightWnd = CreateWindowEx(WS_EX_CLIENTEDGE, m_lpszRightClassName, TEXT(""),
                                     WS_CHILD | WS_VISIBLE | SS_SUNKEN,
                                     rect.left + m_nSplitterWidth,
                                     rect.top,
                                     rect.right - m_nSplitterWidth,
                                     rect.bottom,
                                     hWnd, NULL, m_hInstance, NULL);
        return 0;
    }
    static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        CMainView *pThis = (CMainView *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
        if (pThis)
        {
            return pThis->WindowProc(hWnd, uMsg, wParam, lParam);
        }
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        switch (uMsg)
        {
        case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            HPEN hPen = CreatePen(PS_NULL, 1, RGB(0, 0, 0));
            HPEN holdPen = (HPEN)SelectObject(hdc, hPen);
            HBRUSH hBrush = CreateSolidBrush(RGB(200, 255, 200));
            HBRUSH holdBrush = (HBRUSH)SelectObject(hdc, hBrush);

            RECT rect;
            GetClientRect(hWnd, &rect);
            Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);

            SelectObject(hdc, holdPen);
            SelectObject(hdc, holdBrush);
            DeleteObject(hPen);
            DeleteObject(hBrush);
            ReleaseDC(hWnd, hdc);
            EndPaint(hWnd, &ps);
            break;
        }
        case WM_CTLCOLORSTATIC:
        {
            HDC hdc = (HDC)wParam;
            SetTextColor(hdc, COLOR_3DFACE);
            return (LRESULT)GetStockObject(COLOR_3DFACE);
        }
        case WM_COMMAND:
        {
            TCHAR szTitle[MAX_PATH] = {0};
            StringCchPrintf(szTitle, 255, TEXT("我收到了: %d"), LOWORD(wParam));
            // MessageBox(0, szTitle, TEXT("我收到了"), MB_OK);
            break;
        }
        case WM_SIZE:
        {
            //获取父窗口调整View窗口大小
            RECT rcParent;
            GetClientRect(m_hParent, &rcParent);
            rcParent.top += m_nToolBarHeight;
            rcParent.bottom -= m_nToolBarHeight;
            MoveWindow(m_hWnd, rcParent.left, rcParent.top, rcParent.right, rcParent.bottom, TRUE);

            RECT rcWnd;
            GetClientRect(m_hWnd, &rcWnd);
            MoveWindow(m_hLeftWnd, rcWnd.left, rcWnd.top, rcWnd.left + m_nSplitterWidth, rcWnd.bottom, TRUE);
            MoveWindow(m_hRightWnd, rcWnd.left + m_nSplitterWidth, rcWnd.top, rcWnd.right - m_nSplitterWidth, rcWnd.bottom, TRUE);
            InvalidateRect(hWnd, NULL, FALSE);
            break;
        }
        case WM_MOUSEMOVE:
        {
            int xPos = LOWORD(lParam);
            int yPos = HIWORD(lParam);
            TCHAR buffer[255];
            StringCchPrintf(buffer, 255, TEXT("xPos: %d, yPos: %d"), xPos, yPos);
            // SetWindowText(m_hParent, buffer);
            break;
        }
        case WM_CLOSE:
        {
            DestroyWindow(hWnd);
            break;
        }
        case WM_DESTROY:
        {
            PostQuitMessage(0);
            break;
        }
        default:
            break;
        }
        return DefWindowProc(m_hWnd, uMsg, wParam, lParam);
    }
    static LRESULT CALLBACK LeftWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        PAINTSTRUCT ps;
        HDC hdc;
        RECT rect;
        static HBRUSH hleft_Wnd_brush = NULL;

        switch (message)
        {
        case WM_CREATE:
            break;
        case WM_PAINT:
            hdc = BeginPaint(hWnd, &ps);
            // TODO: Add any drawing code here...
            GetClientRect(hWnd, &rect);
            hleft_Wnd_brush = GetSysColorBrush(COLOR_3DSHADOW);
            FillRect(hdc, &rect, hleft_Wnd_brush);
            DeleteObject(hleft_Wnd_brush);
            EndPaint(hWnd, &ps);
            break;
        case WM_CLOSE:
        {
            DestroyWindow(hWnd);
        }
        break;
        case WM_DESTROY:
        {
            PostQuitMessage(0);
        }
        break;
        default:
            break;
        }
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    static LRESULT CALLBACK RightWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        PAINTSTRUCT ps;
        HDC hdc;
        RECT rect;
        static HBRUSH hright_Wnd_brush = NULL;
        switch (message)
        {
        case WM_CREATE:
            break;
        case WM_PAINT:
            hdc = BeginPaint(hWnd, &ps);
            // TODO: Add any drawing code here...
            GetClientRect(hWnd, &rect);
            hright_Wnd_brush = GetSysColorBrush(COLOR_3DSHADOW);
            FillRect(hdc, &rect, hright_Wnd_brush);
            DeleteObject(hright_Wnd_brush);
            EndPaint(hWnd, &ps);
            break;
        case WM_CLOSE:
        {
            DestroyWindow(hWnd);
        }
        break;
        case WM_DESTROY:
        {
            PostQuitMessage(0);
        }
        break;
        default:
            break;
        }
        return DefWindowProc(hWnd, message, wParam, lParam);
    }

private:
    UINT m_nMenuBarHeight;
    UINT m_nToolBarHeight;
    HWND m_hWnd;
    HWND m_hParent;
    HFONT m_hFont;
    HWND m_hLeftWnd;
    HWND m_hRightWnd;
    UINT m_nSplitterWidth;
    LPCTSTR m_lpszMainClassName;
    LPCTSTR m_lpszLeftClassName;
    LPCTSTR m_lpszRightClassName;
    WNDCLASSEX m_wcex;
    RECT m_rcMenuBar;
    RECT m_rcToolBar;
    HINSTANCE m_hInstance;
};

#endif
